home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1990
/
12
/
crocker.asc
< prev
next >
Wrap
Text File
|
1990-11-15
|
14KB
|
351 lines
_DESIGNING AN OSI TEST BED_
by Kenneth L. Crocker and Michael T. Thompson
[LISTING ONE]
/*########## INITIALIZE INTERRUPTS, X.25 & TRANSPORT LAYER DATA #########*/
/* AUTHOR: Michael T. Thompson, Planning Systems Inc. */
/* 2-16-89 for Mitre Corp. (W85) */
/* initialize interrupt routines */
#include <stdio.h> /* MicroSoft "C" 5.1 " */
#include <dos.h> /* MS-DOS 3.30 */
#include <ctype.h>
extern interrupt far clock(); /* Retix clock routine */
extern interrupt far rcvdata(); /* Interrupt interface routine */
extern buf_type bfh_head;
extern unsigned char *rcvdat; /* Common Receiver buffer pointer varible */
extern buf_type rcvbuf; /* Receiver User Data buffer pointer */
extern int icnt, rbufcnt; /* Number of pointers not used in Baddr Array */
extern buf_type Baddr[]; /* Array of buffer pointers */
int xbufsiz=256; /* Standard Buffer size */
int number_of_buffers=30; /* Total number of transmit and receive buffers */
/* ----- Primary system Initialization routine ----- */
x25_init()
{
int i, tbufsiz, result; /* Local varibles */
tbufsiz = xbufsiz + 30; /* Buffer size plus header data */
_disable(); /* disable interrupts while initializing */
init_memory(); /* get available memory from DOS */
init_bufpool(&bpool,tbufsiz,number_of_buffers); /* setup buffer pool */
init_timers(); /* initialize system timers */
init_rcvbuf(); /* initialize receive buffers */
cominz(); /* initialize clock and I/O Interrupt routines */
_enable(); /* start interrupts backup */
}
/*------------------- Initialize Receive Buffer Array --------------------*/
init_rcvbuf()
{
int i;
for(i=0;i<10;i++) /* store pointers in buffer array */
Baddr[i] = getbuf(&bpool,xbufsiz+30); /* +30 for X.25 header info */
rbufcnt = 9; /* 0 to 9 = 10 buffers */
rcvbuf = Baddr[rbufcnt]; /* preallocate first buffer pointer */
Baddr[rbufcnt] = (buf_type) NULL; /* clear the array pointer */
rcvdat = (char *)(BuffData(rcvbuf)); /* point to the user space */
icnt = 0; /* zero frame character count */
}
/* ######################## COMINZ.C ########################## */
/* Initialize the Clock and Synchronous Interrupt routines */
cominz()
{
unsigned intnum;
unsigned int val; /* local varibles */
/* install MAC I/O driver */
intnum = 0x1c; /* Clock interrupt vector */
_dos_setvect(intnum,clock); /* setup new clock interrupt routine */
istart(); /* enable I/O interrupt processing */
intnum = 0x0c; /* I/O interrupt vector */
_dos_setvect(intnum,rcvdata); /* setup tx & rx interrupt routine */
val = inp(0x21);
outp(0x21,(val & 0xc7)); /* start irq 3, 4, & 5 */
}
/* ++++++++++++++++ INITIALIZE SEALEVEL BOARD +++++++++++++++++ */
istart()
{
unsigned char InitArray[50]; /* Allocate the size of the Init Array */
int iCount;
/*------------------- Section # 1 ---------------------*/
InitArray[0] = 9;
InitArray[1] = 0xC0; /* force hardware reset */
InitArray[2] = 0;
InitArray[3] = 0x00;
InitArray[4] = 4;
InitArray[5] = 0x20; /* (SDLC) mode selected */
InitArray[6] = 3;
InitArray[7] = 0xC0; /* rx 8 bits, sync char inhabit */
InitArray[8] = 5;
InitArray[9] = 0x61; /* tx 8 bits */
InitArray[10] = 6;
InitArray[11] = 0; /* For Mono-sync */
InitArray[12] = 7;
InitArray[13] = 0x7E; /* sdlc sync character */
InitArray[14] = 10;
InitArray[15] = 0x80; /* CRC set to inverted bit pattern */
InitArray[16] = 11;
InitArray[17] = 0; /* for dte clock from RTxC pin */
InitArray[18] = 12;
InitArray[19] = 0xFE; /* Low order baud rate value */
InitArray[20] = 13;
InitArray[21] = 00; /* High order baud rate value */
/* H L */
/* 38400 = 00 3E */
/* 19200 = 00 7E */
/* time constant: 9600 = 00 FE */
/* 4800 = 01 FE */
InitArray[22] = 14;
InitArray[23] = 2; /* gen enabled, gen source */
/*------------------- Section # 2 ---------------------*/
InitArray[24] = 14;
InitArray[25] = 3; /* gen enabled, gen source */
InitArray[26] = 3;
InitArray[27] = 0xD9; /* rx 8 bits, hunt mode, rx CRC, rx enabled */
InitArray[28] = 5;
InitArray[29] = 0x69; /* tx 8 bits, tx enabled, tx CRC */
InitArray[30] = 0;
InitArray[31] = 0x80; /* tx CRC gen */
InitArray[32] = 1; /* int on all rx chars or special cond. */
InitArray[33] = 0x12; /* enable tx interrupts */
/*------------------- Section # 3 ---------------------*/
InitArray[34] = 15;
InitArray[35] = 0x41; /* tx underrun int enabled */
InitArray[36] = 0;
InitArray[37] = 0x30; /* error reset */
InitArray[38] = 0;
InitArray[39] = 0x90; /* tx CRC gen, reset ext/status int */
InitArray[40] = 0;
InitArray[41] = 0x90; /* twice */
InitArray[42] = 1; /* int on all rx chars or special cond. */
InitArray[43] = 0x12; /* enable tx interrupts */
InitArray[44] = 9;
InitArray[45] = 8; /* Master int enable */
InitArray[46] = 0;
InitArray[47] = 0xF0; /* reset tx underrun, error reset */
InitArray[48] = 0;
InitArray[49] = 0x28; /* reset tx int pending */
for (iCount = 0; iCount < 50; iCount++)
outp(0x239,InitArray[iCount]); /* Output Data to SDLC Chip */
}
[LISTING TWO]
/********************************************************************
* RCV2.C -- Interrupt Handler routine for use with the Sealevel *
* Systems synchronous communications board that uses preallocated *
* buffers to Transmitt and Receive X.25 data frames. *
********************************************************************/
/* AUTHORS - Michael T. Thompson, Planning Systems Inc. and
* Ken Crocker, The MITRE Corporation 5/23/89
*/
#include <stdio.h> /* MicroSoft "C" 5.1 " */
#include <dos.h> /* MS-DOS 3.30 */
#include <ctype.h>
/* RETIX OSI SOFTWARE COMMON HEADER FILES */
#include "c:\retix\include\bufflib.h"
#include "c:\retix\include\common.h"
#include "c:\retix\include\system.h"
#include "c:\retix\include\lapb.h"
#include "c:\retix\include\address.h"
#include "c:\retix\include\network.h"
#include "c:\retix\include\x25.h"
extern buf_type MDATcon(); /* Data Confirm routine */
extern struct sp_ent *mac; /* Service provider table */
extern xbufsiz; /* Current TPDU buffer size */
extern vpmidi(); /* MDATind Data Indiction routine */
unsigned char *rcvdat; /* Pointer to received user data input buffer */
buf_type rcvbuf; /* Pointer to received buffer header */
buf_type Baddr[10]; /* Array of allocated receive buffer pointers */
int icnt, rbufcnt, fcnt; /* Receiver and Transmitter counters */
int fsize; /* Size of Transmit Frame */
char *frame; /* Temporary pointer to Transmit frame */
/************************** RCVDATA.C ****************************
* Interrupt Driven Receiver and Transmitter *
* RECEIVER: On the receive side an array of buffer pointers is *
* allocated in the x251t.c initialization Routine. The first *
* buffer is preassigned to the receive routine and then that *
* buffer can be written to by the interrupt routine. When the *
* last character of the frame is received the MDATind (vpmidi) *
* routine is called and the new buffer is put on the queue for *
* processing later. After that we get the address of another *
* preallocated buffer from the array and setup the proper *
* pointers. *
*****************************************************************/
void interrupt cdecl rcvdata()
{
unsigned int c, c1, delay; /* local varibles */
_enable(); /* enable interrupts */
/* check if this is an error, a receive or a transmitt interrupt */
outp(0x239,3);
delay = 0; /* allow time for the register to setup */
if(((c = inp(0x239)) & 0x30) != 0) /* if not an error continue */
{
if((c & 0x20) != 0) /* if not receive interrupt continue */
{
/******** RECEIVE DRIVER *********/
/* we must have receive data */
/*********************************/
rcvdat[icnt++] = inp(0x238); /* get character and store it */
outp(0x239,1);
delay = 0;
if(((c1 = inp(0x239)) & 0x80) != 0) /* check for end of frame */
{
if((c1 & 0x70) == 0) /* check for a valid CRC */
{ /* must be OK */
if(icnt > 3)
{
rcvdat[icnt-2] = 0;
BuffAdjust(rcvbuf,((xbufsiz+30)-(icnt-2)));
/* reajust buffer size for lapb */
vpmidi(rcvbuf,mac);
/* send MDATind to service user */
icnt = 0;
while(Baddr[--rbufcnt] == (buf_type) NULL);
/* Find an unused buffer pointer */
rcvbuf = Baddr[rbufcnt];
/* got a new receive buffer pointer */
Baddr[rbufcnt] = (buf_type) NULL;
/* clear buffer pointer from array */
rcvdat = (char *)(BuffData(rcvbuf));
/* setup receive data pointer */
/* check for a transmit interrupt pending */
if((c & 0x10) == 0)
goto ENDINT; /* no interrupt so end */
/* found transmit interrupt pending so send it */
goto TXINT;
}
/* frame is to short so go to error reset */
goto ERRRES;
}
/* We got a BAD CRC */
goto ERRRES; /* goto error reset */
}
/* not end of frame so check for a transmit interrupt pending */
if((c & 0x10) == 0)
/* no transmit interrupt so end interrupt routine */
goto ENDINT;
}
TXINT:/************************ TRANSMIT DRIVER *****************************/
/* After we have determined that we have received a transmit interrupt*/
/* we check to see if we are at end of frame by checking its size. If */
/* not, then we send out character pointed at by frame pointer and */
/* then end the interrupt. If we are at end of frame, we clear frame */
/* counter and reset the transmit interrupt flag. */
/**********************************************************************/
if(fsize > 0) /* are at the end of the frame ? */
{
fsize--; /* decrement frame size */
outp(0x238,frame[fcnt++]); /* NO - send character */
goto ENDINT; /* end the interrupt routine */
}
outp(0x239,0); /* must be at the end of the frame */
fcnt = 0; /* clear the frame count */
outp(0x239,0x28); /* reset transmit interrupts */
goto ENDINT; /* end the interrupt routine */
}
ERRRES:
outp(0x239,0); /* error reset */
icnt = 0; /* reuse the same buffer */
outp(0x239,0x30);
ENDINT:
outp(0x20,0x20); /* End of interrupt report */
return;
}
/******************************** MDATreq() **********************************
* MDATreq: Transmit LAPB output requests. When a buffer is ready to be *
* transmitted, that buffer is sent to MDATreq routine where we check to see*
* if data is currently being transmitted. If it is, we return to calling *
* routine and try again later. If no data is being transmitted, we check *
* transmit buffer register of synchronous controller chip to see if it is *
* empty so that when it is, we can send out first character of frame. When *
* we can send out a character the pointers and counters are setup and *
* first character is sent. After first character is sent, buffer is removed*
* from outbound queue and a second character is sent to help with system *
* timing. At this point, interrupt driver will take over and continue to *
* send remaining data until last byte of frame is delivered along with *
* frames CRC. *
*****************************************************************************/
void MDATreq (msdu)
buf_type msdu; /* Transmitt buffer pointer */
{
int rval, delay; /* local varibles */
if(fsize != 0) /* if we are still transmitting a frame return */
return;
outp(0x239,0);
fcnt=0;
while (((rval = inp(0x239)) & 4) == 0); /* test for buffer empty */
frame = (char *)(BuffData(msdu)); /* get pointer to user buffer */
fsize = (BuffSize(msdu)-1); /* get size minus first char */
QRemove(msdu); /* remove buffer from queue */
delay=0;
outp(0x238,frame[fcnt++]); /* send first byte of frame */
msdu=(buf_type)MDATcon(msdu,mac); /* and confirm the buffer */
while (((rval = inp(0x239)) & 4) == 0); /* test for buffer empty */
fsize--; /* decrement frame size */
outp(0x238,frame[fcnt++]); /* send second byte of frame */
outp(0x239,0);
delay = 0;
outp(0x239,0xC0); /* process end of frame CRC */
return;
}
[LISTING THREE]
/****************************************************************************
* Poll timer queue for any expired timers. Next check to see if there is *
* any X.25 traffic to be moved on Inbound or Outbound packet queue. The *
* last process we check is if Baddr Array is low on preallocated receive *
* buffers that are used by RCV2.C Interrupt Handler. *
****************************************************************************/
/* AUTHOR - Michael T. Thompson, Planning Systems Inc. 5/23/89 */
poldat()
{
int i; /* index varible */
do_timer_queue(); /* Test for expaired timers */
do_lapb_queue(); /* Check for X.25 Traffic */
if(rbufcnt < 4) /* replenish array if less than four pointers */
{
for(i=0;i<9;i++) /* check all receive buffers */
{
if(Baddr[i] == NULL) /* If Null, pointer has been used */
{ /* Get new buffer pointer & assign it to the array */
Baddr[i] = getbuf(&bpool,xbufsiz+30);
rbufcnt++; /* Increment buffer count */
}
}
}
} /* END OF POLDAT */